package com.hunttown.mes.manage.controller._basic;

import com.hunttown.mes.common.qcloud.qcloudcos.CosConstants;
import com.hunttown.mes.common.qcloud.qcloudcos.CosUtils;
import com.hunttown.mes.common.utils.GeneralUtils;
import com.hunttown.mes.common.utils.GetRandomUtils;
import com.hunttown.mes.common.utils.StringUtils;
import com.hunttown.mes.manage.controller.common.AdminBaseClass;
import com.hunttown.mes.manage.service.AnalysisConfigParamManageService;
import com.hunttown.mes.manage.service.AnalysisManageManageService;
import com.hunttown.mes.manage.service.TransportTableChineseEnglishManageService;
import com.hunttown.mes.manage.service.TransportUploadFilesManageService;
import com.hunttown.mes.manage.service.files.FileSystemStorageManageService;
import com.hunttown.mes.rpc.domain.AnalysisManageDTO;
import com.hunttown.mes.rpc.domain.TransportTableChineseEnglishDTO;
import com.hunttown.mes.rpc.domain.TransportUploadFilesDTO;
import com.hunttown.mes.rpc.domain.enums.upload.ServiceTypeEnum;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @title: 文件上传
 * @author: wangjunfu
 * @date: 2020-06-13
 * @description:
 */
@Controller
@RequestMapping(value = "/basic/upload")
public class UploadController extends HttpServlet {
    private final static Logger logger = LoggerFactory.getLogger(UploadController.class);

    @Value("${filesite.domain}")
    private String fileSite;

    private final AnalysisManageManageService manageService;
    private final AnalysisConfigParamManageService configParamService;
    private final TransportUploadFilesManageService uploadFilesService;
    private final TransportTableChineseEnglishManageService englishService;
    private final FileSystemStorageManageService fileSystemStorageManageService;

    @Autowired
    public UploadController(AnalysisManageManageService manageService, AnalysisConfigParamManageService configParamService, TransportUploadFilesManageService uploadFilesService, TransportTableChineseEnglishManageService englishService, FileSystemStorageManageService fileSystemStorageManageService) {
        this.manageService = manageService;
        this.configParamService = configParamService;
        this.uploadFilesService = uploadFilesService;
        this.englishService = englishService;
        this.fileSystemStorageManageService = fileSystemStorageManageService;
    }

    //region 上传文件

    /**
     * 上传文件
     *
     * @return vm
     */
    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index() {
        return "basic/upload/index";
    }
    //endregion

    //region 上传数据

    /**
     * 上传数据
     *
     * @param request req
     * @param file    要上传的文件
     * @return map
     */
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> updload(HttpServletRequest request, @RequestParam("file") MultipartFile[] file) {

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("returnCode", 0);

        String tableName = request.getParameter("uploadTableName");
        String recordId = request.getParameter("uploadRecordId");
        String prefix = request.getParameter("uploadPrefix");

        //region 记录ID
        Integer _recordId = 0;
        if (StringUtils.isNotBlank(recordId) && !recordId.equals("0")) {
            _recordId = Integer.valueOf(recordId);
        }
        //endregion

        //region 简单理解：远程保存文件夹
        if (StringUtils.isBlank(prefix)) {
            prefix = "file";
        }

        switch (prefix.toLowerCase()) {
            case "image":
                prefix = CosConstants.ImagePrefix;
                break;
            case "repair":
                prefix = CosConstants.RepairPrefix;
                break;
            case "safety":
                prefix = CosConstants.SafetyPrefix;
                break;
            default:
                prefix = CosConstants.FilePrefix;
        }
        //endregion

        //region 通过tablename 获取tabileId
        if (StringUtils.isBlank(tableName)) {
            map.put("returnMessage", "未获取到当前数据表信息！");
            return map;
        }

        TransportTableChineseEnglishDTO englishDTO = englishService.getByTableName(tableName);
        if (englishDTO == null) {
            map.put("returnMessage", "未获取到当前数据表信息！");
            return map;
        }
        //endregion

        //存储上传结果
        List<HashMap<String, String>> uploadMap = new ArrayList<>();
        HashMap<String, String> temp;

        //region 存储参数

        //从参数中获取COS提供商
        Integer cosService = configParamService.getByParamKey("cosservice-supplier", 0);
        if (cosService < 0 || cosService > 1) {
            map.put("returnCode", 0);
            map.put("returnMessage", "请先配置文件存储服务器！");
            return map;
        }

        //如果是本地存储，要获取本地存储文件夹
        String cosSavePath = "/root/upload_dir";
        if (cosService == 0) {
            cosSavePath = configParamService.getByParamKey("local-cos-path", "");
        }

        //获取可上传文件夹大小
        String uploadFileSize = configParamService.getByParamKey("upload-file-type", "");
        if (StringUtils.isBlank(uploadFileSize)) {
            map.put("returnCode", 0);
            map.put("returnMessage", "请先配置可上传文件类型！");
            return map;
        }

        //JSON格式
        JSONObject fileJson = new JSONObject(uploadFileSize.toLowerCase());

        //endregion

        //当前操作人员
        String pin = AdminBaseClass.getPin(request);
        AnalysisManageDTO curr_obj = manageService.getFromCachePin(pin);

        for (MultipartFile item : file) {

            //获取文件名
            String filename = item.getOriginalFilename();

            //获取文件后缀名
            String suffix = filename.substring(filename.lastIndexOf(".") + 1);

            //文件唯一标识
            String onlykey = GetRandomUtils.GetRandom(32);
            String preOnlykey = onlykey + "." + suffix; //唯一文件名
            String nextOnlykey = prefix + preOnlykey;   //带目录的文件名
            String finalOnlykey = preOnlykey;           //将目录转化为文件名

            //首先判断文件名是否允许
            if (!fileJson.has(suffix.trim().toLowerCase())) {
                map.put("returnCode", 0);
                map.put("returnMessage", "此文件格式【" + suffix + "】不支持上传！");
                return map;
            }

            //再判断文件大小
            int size = fileJson.getInt(suffix.trim().toLowerCase());
            if (size < (item.getSize() / 1000)) {
                map.put("returnCode", 0);
                map.put("returnMessage", "文件大小已超出" + size + "K的限制！");
                return map;
            }

            //返回值
            Map<String, String> resultMap = new HashMap<>();

            //region 本地上传
            if (cosService == 0) {
                if (StringUtils.isBlank(cosSavePath)) {
                    map.put("returnCode", 0);
                    map.put("returnMessage", "请先配置存储路径！");
                    return map;
                }

                //说明一下，nio类无法创建文件夹

                if (cosSavePath.startsWith("/")) {
                    //说明是linux服务
                    if (cosSavePath.endsWith("/")) {
                        cosSavePath = cosSavePath.substring(0, cosSavePath.lastIndexOf("/"));
                    }

                } else {
                    //说明是windows服务器
                    if (cosSavePath.endsWith("\\")) {
                        cosSavePath = cosSavePath.substring(0, cosSavePath.lastIndexOf("\\"));
                    }
                }

                //把日期文件夹和业务文件夹都加到文件名上
                if (prefix.startsWith("/")) {
                    prefix = prefix.substring(1);
                }

                finalOnlykey = prefix.replace("/", "-") + finalOnlykey;

                fileSystemStorageManageService.store(item, finalOnlykey, cosSavePath);

                resultMap.put("code", "0");
            }
            //endregion

            //region 腾讯云上传

            //配置表获取
            String secretId = configParamService.getByParamKey("cos-tencent-secretid", "");
            String secretKey = configParamService.getByParamKey("cos-tencent-secretkey", "");
            String region = configParamService.getByParamKey("cos-tencent-region", "");
            String bucket = configParamService.getByParamKey("cos-tencent-bucket", "");

            if (cosService == 1) {
                resultMap = tencentUpload(item, secretId, secretKey, region, bucket, nextOnlykey);
            }
            //endregion

            //如果没有服务提供商则返回
            if (resultMap.size() == 0) {
                continue;
            }

            //region 上传成功后，保存在文件上传表
            if (resultMap.get("code").equals("0")) {
                TransportUploadFilesDTO dto = new TransportUploadFilesDTO();
                dto.setTableId(englishDTO.getId());
                dto.setRecordId(_recordId);
                dto.setDocumentType(0);
                dto.setFileName(filename);
                dto.setFileSize(item.getSize());
                dto.setContentType(item.getContentType());

                //本地上传
                if (cosService == 0) {
                    dto.setServiceType(ServiceTypeEnum.LOCAL.getKey());
                    dto.setAbsolutePath(cosSavePath);
                    dto.setSavePath(prefix);
                    dto.setOnlyKey(finalOnlykey);
                    dto.setEtag(onlykey);
                    dto.setWebUrl("/files/cos/img?etag=" + onlykey);
                }

                //腾讯云上传
                if (cosService == 1) {
                    dto.setServiceType(ServiceTypeEnum.TENCENT.getKey());
                    dto.setBucketName(bucket);
                    dto.setOnlyKey(nextOnlykey);
                    dto.setStorageClass("Standard_IA");
                    dto.setEtag(resultMap.get("etag"));
                    dto.setWebUrl(CosConstants.getPreFixedUrl(bucket, region, nextOnlykey));
                }

                dto.setAdminId(curr_obj.getId());
                dto.setCreateTime(new Date());
                dto.setStopFlag(0);
                dto.setDeleteFlag(0);
                dto = uploadFilesService.insert(dto);

                if (dto == null || dto.getId() == null || dto.getId() <= 0) {
                    map.put("returnMessage", "文件上传失败！");
                    return map;
                }

                temp = new HashMap<>();
                temp.put("id", dto.getId() + "");
                temp.put("servicetype", dto.getServiceType() + "");
                temp.put("url", dto.getWebUrl());
                temp.put("name", dto.getFileName());

                String pic = GeneralUtils.getContentTypeUrl(dto.getContentType());
                if (StringUtils.isBlank(pic)) {
                    pic = dto.getWebUrl();
                }
                temp.put("pic", pic);

                uploadMap.add(temp);
            }
            //endregion
        }

        map.put("upload", uploadMap);
        map.put("returnCode", 1);
        map.put("returnMessage", "文件上传成功！");
        return map;
    }
    //endregion

    //region 腾讯云上传
    private Map<String, String> tencentUpload(MultipartFile file, String secretId, String secretKey, String region, String bucket, String onlykey) {

        //开始上传
        String etag = CosUtils.uploadCos(secretId, secretKey, region, bucket, file, onlykey);

        Map<String, String> map = new HashMap<>();
        map.put("code", "0");
        map.put("etag", etag);
        return map;
    }
    //endregion

    //region 预览文件（腾讯云）

    /**
     * 预览文件（腾讯云）
     *
     * @param fileId 文件ID
     * @return map
     */
    @RequestMapping(value = "/view", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> view(HttpServletRequest request, Integer fileId) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("returnCode", 0);
        map.put("fileSite", fileSite);

        if (fileId == null || fileId <= 0) {
            map.put("returnMessage", "未查询到预览文件");
            return map;
        }

        TransportUploadFilesDTO filesDTO = uploadFilesService.getById(fileId);
        if (filesDTO == null) {
            map.put("returnMessage", "未查询到预览文件");
            return map;
        }

        //判断文件类型
        String type = GeneralUtils.getContentType(filesDTO.getContentType());
        map.put("type", type);

        if (type.equals("img") || type.equals("pdf")) {
            //图片和PDF
            map.put("weburl", filesDTO.getWebUrl());
        } else {
            //其它需要转换的文档，如：word excel ppt txt...
            map.put("weburl", "/");
        }

        map.put("returnCode", 1);
        return map;
    }
    //endregion
}
